package com.zhiwen.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.zhiwen.common.exception.BusinessException;
import com.zhiwen.domain.dto.LoginDTO;
import com.zhiwen.domain.dto.RegisterDTO;
import com.zhiwen.domain.entity.User;
import com.zhiwen.service.AuthService;
import com.zhiwen.service.UserService;
import com.zhiwen.domain.vo.UserVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 认证服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AuthServiceImpl implements AuthService {

    private final UserService userService;
    private final BCryptPasswordEncoder passwordEncoder;
    private final RedisTemplate<String, String> redisTemplate;

    @Override
    public Map<String, Object> login(LoginDTO loginDTO) {
        // 查询用户
        User user = userService.getByAccount(loginDTO.getAccount());
        if (user == null) {
            throw new BusinessException("账号不存在");
        }

        // 校验密码
        if (!passwordEncoder.matches(loginDTO.getPassword(), user.getPassword())) {
            throw new BusinessException("密码错误");
        }

        // 校验用户状态
        if (user.getStatus() == 0) {
            throw new BusinessException("账号已被禁用");
        }

        // 更新登录时间
        user.setLastLoginTime(LocalDateTime.now());
        userService.updateById(user);

        // 执行登录
        StpUtil.login(user.getId());

        // 获取token信息
        Map<String, Object> tokenInfo = new HashMap<>(2);
        tokenInfo.put("tokenName", StpUtil.getTokenName());
        tokenInfo.put("tokenValue", StpUtil.getTokenValue());

        return tokenInfo;
    }

    @Override
    public UserVO register(RegisterDTO registerDTO) {
        return userService.register(registerDTO);
    }

    @Override
    public UserVO getCurrentUser() {
        // 获取当前登录用户ID
        Long userId = StpUtil.getLoginIdAsLong();

        // 查询用户信息
        User user = userService.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        return userService.getUserVO(user);
    }

    @Override
    public void logout() {
        StpUtil.logout();
    }

    @Override
    public Map<String, String> generateCaptcha(String email) {
        if (email == null || email.isEmpty()) {
            throw new BusinessException("邮箱不能为空");
        }

        // 生成6位随机验证码
        String captcha = generateRandomCode(6);

        // 生成唯一的captchaKey
        String captchaKey = System.currentTimeMillis() + "_" + email;

        // 将验证码存入Redis，5分钟过期
        redisTemplate.opsForValue().set("captcha:" + captchaKey, captcha, 5, TimeUnit.MINUTES);

        // TODO: 在实际环境中，这里应该发送邮件，但现在为了测试方便，直接返回验证码
        log.info("向邮箱 {} 发送验证码: {}", email, captcha);

        Map<String, String> result = new HashMap<>(2);
        result.put("captchaKey", captchaKey);
        // 在生产环境中不应该返回验证码，这里为了测试方便
        result.put("captcha", captcha);

        return result;
    }

    /**
     * 生成指定长度的随机数字验证码
     */
    private String generateRandomCode(int length) {
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            sb.append(random.nextInt(10));
        }
        return sb.toString();
    }
}
